package com.anlogic.sdk.dumprestorememory.ui;

import java.io.File;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import com.anlogic.sdk.dumprestorememory.DumpRestoreModel;
import com.anlogic.sdk.dumprestorememory.exception.NotOverWriteFileException;

public class DumpRestoreDialog extends TitleAreaDialog {
	private Combo chipCombo;

	private Text fileLocationText;
	private Button fileLocationButton;
	private Button[] readWriteButtons;
	private Text startAddr;
	private Text sizeText;
	private String[] chipType = new String[] { "dr1m90", "dr1v90", "ph1p35" };
	private String[] FileFilters = new String[] { "*.bin; *.mcs;*.dtb;*.fat;*.scr;*.lz4", "*.*" };
	protected DumpRestoreModel model;

	private Combo targetSelectCombo;

	public DumpRestoreDialog(Shell parentShell) {
		super(parentShell);
		setShellStyle(getShellStyle() | SWT.RESIZE);
	}

	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		newShell.setText("Dump/Restore Memory");
		enbaleOkButton(false);
	}

	@Override
	protected Control createButtonBar(Composite parent) {
		isLocationvalidate();
		return super.createButtonBar(parent);
	}

	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		super.createButtonsForButtonBar(parent);
		enbaleOkButton(false);
	}

	private void enbaleOkButton(boolean flag) {
		Button button = getButton(0);
		if (button != null)
			button.setEnabled(flag);
	}

	@Override
	protected Control createDialogArea(Composite parent) {
		
		setTitle("Dump/Restore Memory");
		setMessage("Dumps Memory Contents to File or Restores File Contents to Memory");

		if (this.model == null) {
			this.model = new DumpRestoreModel();

		}

		Composite container = new Composite(parent, SWT.DEFER);
		container.setLayout(new GridLayout(3, false));
		container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		Label procLabel = new Label(container, SWT.NULL);
		procLabel.setText("Chip:");
		chipCombo = new Combo(container, SWT.POP_UP);
		GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo((Control) chipCombo);
		chipCombo.setItems(chipType);
		chipCombo.select(0);
		
		Label targetSelectLabel = new Label(container, SWT.NULL);
		targetSelectLabel.setText("Connection:");
		targetSelectCombo = new Combo(container, SWT.POP_UP);
		targetSelectCombo.add("Local");
		targetSelectCombo.select(0);
		GridDataFactory.fillDefaults().grab(true, false).applyTo((Control) targetSelectCombo);
	
		Button targetCreateButton = new Button(container, SWT.PUSH);
		targetCreateButton.setText("New");
		GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).applyTo((Control) targetCreateButton);

		

		Label FileLocationLabel = new Label(container, SWT.NULL);
		FileLocationLabel.setText("File Location:");
		fileLocationText = new Text(container, SWT.BORDER);
		GridDataFactory.fillDefaults().grab(true, false).applyTo((Control) fileLocationText);
		fileLocationButton = new Button(container, SWT.PUSH);
		fileLocationButton.setText("Browse");
		Composite radioComposite = new Composite(container, SWT.NULL);
		GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo((Control) radioComposite);
		GridLayoutFactory.fillDefaults().numColumns(2).applyTo(radioComposite);
		readWriteButtons = new Button[2];
		readWriteButtons[0] = new Button(radioComposite, SWT.RADIO);
		readWriteButtons[0].setSelection(true);
		readWriteButtons[0].setText("Dump Memory");
		readWriteButtons[0].pack();
		readWriteButtons[1] = new Button(radioComposite, SWT.RADIO);
		readWriteButtons[1].setText("Restore Memory");
		readWriteButtons[1].setSelection(false);
		readWriteButtons[1].pack();
		Group group = new Group(container, SWT.NULL);
		GridLayout layout = new GridLayout();
		layout.verticalSpacing = 0;
		layout.numColumns = 2;
		group.setLayout((Layout) layout);
		group.setLayoutData(new GridData(1808));
		group.setFont(container.getFont());
		group.setText("Memory Details");
		Label addrLabel = new Label((Composite) group, 64);
		addrLabel.setLayoutData(new GridData(32));
		addrLabel.setFont(container.getFont());
		addrLabel.setText("Start Address:");
		startAddr = new Text((Composite) group, 2052);
		startAddr.setLayoutData(new GridData(768));
		startAddr.setFont(container.getFont());
		startAddr.setEnabled(true);
		GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo((Control) group);
		Label sizeLabel = new Label((Composite) group, 64);
		sizeLabel.setLayoutData(new GridData(32));
		sizeLabel.setFont(container.getFont());
		sizeLabel.setText("Size(in bytes):");
		sizeText = new Text((Composite) group, 2052);
		sizeText.setLayoutData(new GridData(768));
		sizeText.setFont(container.getFont());
		sizeText.setEnabled(true);
		GridDataFactory.fillDefaults().grab(true, false).span(3, 1).applyTo((Control) group);
		addListeners();
		return super.createDialogArea(parent);
	}

	private void addListeners() {
		fileLocationText.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e) {
				isLocationvalidate();
			}
		});
		fileLocationButton.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
				dialog.setFilterExtensions(FileFilters);
				String result = dialog.open();
				if (result != null) {
					fileLocationText.setText(result);

				}
			}
		});
		startAddr.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e) {
				isLocationvalidate();
			}
		});
		sizeText.addModifyListener(new ModifyListener() {

			@Override
			public void modifyText(ModifyEvent e) {
				isLocationvalidate();

			}
		});
		readWriteButtons[0].addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				isLocationvalidate();
			}
		});
		readWriteButtons[1].addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				isLocationvalidate();
			}
		});

	}

	@Override
	protected void okPressed() {
		try {
			validate();
		} catch (NotOverWriteFileException e) {
			return;
		} catch (Exception e) {
			MessageBox mb = new MessageBox(getShell(), SWT.HardKeyDown);
			mb.setText("Invalid data");
			mb.setMessage(e.getMessage());
			mb.open();
		}
		updateModel();
		super.okPressed();
	}

	private void updateModel() {
		this.model.setChip(chipCombo.getText());
		String binFile = new Path(fileLocationText.getText()).toString();
		this.model.setBinFile(binFile);
		this.model.setStartAddr(startAddr.getText());
		this.model.setSize(sizeText.getText());
		boolean selection = readWriteButtons[0].getSelection();
		this.model.setDump(selection);
	}

	public DumpRestoreModel getModel() {
		return model;
	}

	private void validate() throws NotOverWriteFileException {
		boolean readSelection = readWriteButtons[0].getSelection();
		if (!readSelection) {
			String fileText = fileLocationText.getText().trim();
			Path path = new Path(fileText);
			File file = new File(path.toOSString());
			file = file.getAbsoluteFile();
			if (!file.exists())
				throw new RuntimeException("File doesn't exist");
			if (!file.isFile()) {
				throw new RuntimeException("Invalid File Path");
			}
			return;
		}
		String fileText2 = fileLocationText.getText().trim();
		Path path = new Path(fileText2);
		String osPath = path.toOSString();
		int folderIndex = osPath.lastIndexOf(File.separator);
		String folderPath = osPath.substring(0, folderIndex);
		Path path2 = new Path(folderPath);
		File file = new File(path2.toOSString());
		file = file.getAbsoluteFile();
		if (!file.exists()) {
			boolean retVal = file.mkdirs();
			if (!retVal)
				throw new RuntimeException("Failed to Create Output Directory");
		}
		Path path3 = new Path(fileText2);
		File file1 = new File(path3.toOSString());
		file1 = file1.getAbsoluteFile();
		if (file1.exists()) {
			MessageDialog dg = new MessageDialog(getShell(), "File Overwrite", null,
					"File already exists in output folder, would like to overwrite?", 6,
					new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL }, 0);
			int open = dg.open();
			if (open == 0) {
				return;
			} else {
				throw new NotOverWriteFileException();
			}
		}

	}

	public boolean isLocationvalidate() {
		boolean writeSelection = readWriteButtons[1].getSelection();
		if (writeSelection == true) {
			String s = fileLocationText.getText().trim();
			Path path = new Path(s);
			File file = new File(path.toOSString());
			file = file.getAbsoluteFile();
			if (!file.exists()) {
				setErrorMessage("File doesn't exist");
				enbaleOkButton(false);
				return false;
			}
			if (!file.isFile()) {
				setErrorMessage("Invalid File Path");
				enbaleOkButton(false);
				return false;
			}
		} else if (writeSelection == false) {
			String s = fileLocationText.getText().trim();
			if (s == null || s.isEmpty()) {
				setErrorMessage("Invalid File Path");
				enbaleOkButton(false);
				return false;
			}
			Path path = new Path(s);
			File file = new File(path.toOSString());
			file = file.getAbsoluteFile();
			if (file.isDirectory()) {
				setErrorMessage("Directory exists with given file name");
				enbaleOkButton(false);
				return false;
			}
			file = file.getParentFile();
			if (!file.exists()) {
				setErrorMessage("Invalid File Path");
				enbaleOkButton(false);
				return false;
			}
		}
		try {
			validateStartAddrAndSize();
		} catch (Exception e) {
			setErrorMessage(e.getMessage());
			enbaleOkButton(false);
			return false;
		}
		setErrorMessage(null);
		enbaleOkButton(true);
		return true;

	}

	private void validateStartAddrAndSize() {
		String startAddrress = startAddr.getText().trim();
		if (startAddrress == null || "".equals(startAddrress) || startAddrress.length() == 0) {
			throw new RuntimeException("Start Address cannot be empty");
		}
		if (!startAddrress.startsWith("0x") && !startAddrress.startsWith("0X")) {
			throw new RuntimeException("Invalid Start Address.");
		}
		String address = startAddrress.substring(2);
		if (!address.matches("-?[0-9A-Fa-f]+")) {
			throw new RuntimeException("Invalid Start Address");
		}
		String size = sizeText.getText().trim();

		if (size == null || "".equals(startAddrress) || size.length() == 0) {
			throw new RuntimeException("size cannot be empty");
		}
		if (!size.matches("\\d+") || size.startsWith("0")) {
			throw new RuntimeException("Invalid Size");
		}

	}

}
